﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Enyim.Caching;

namespace AFT.Parking.Foundation.Caching
{
    public class Memcached : IMemcached
    {
        private static MemcachedClient client = MemcachedManager.Client;

        #region Memcached

        #region 获取数据
        /// <summary>
        /// 获取字符数据
        /// </summary>
        /// <param name="key">key</param>
        /// <returns>value</returns>
        public string GetString(string key)
        {
            return client.Get(key).ToString();
        }

        /// <summary>
        /// 获取数据
        /// </summary>
        /// <typeparam name="T">T</typeparam>
        /// <param name="key">key</param>
        /// <returns>T</returns>
        public T Get<T>(string key)
        {
            return client.Get<T>(key);
        }

        /// <summary>
        /// 获取带CAS的数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public MemcachedValue GetWithCas(string key)
        {
            var result = client.GetWithCas(key);
            MemcachedValue mv = new MemcachedValue()
            {
                Value = result.Result,
                Version = result.Cas
            };
            return mv;
        }

        /// <summary>
        /// 批量获取数据
        /// </summary>
        /// <param name="keys">key集合</param>
        /// <returns>数据词典</returns>
        public IDictionary<string, object> GetMulti(IEnumerable<string> keys)
        {
            return client.Get(keys);
        }

        /// <summary>
        /// 批量获取带CAS的值
        /// </summary>
        /// <typeparam name="?"></typeparam>
        /// <param name="keys"></param>
        /// <returns></returns>
        public IDictionary<string, MemcachedValue> GetMultiWithCas(IEnumerable<string> keys)
        {
            IDictionary<string, MemcachedValue> dics = null;
            var results = client.GetWithCas(keys);
            if (results != null && results.Count > 0)
            {
                foreach (var k in results)
                {
                    MemcachedValue mv = new MemcachedValue()
                    {
                        Value = k.Value.Result,
                        Version = k.Value.Cas
                    };
                    dics.Add(k.Key, mv);
                }
            }
            return dics;
        }

        #endregion

        #region 增加缓存值
        /// <summary>
        /// 增加一个缓存值（仅缓存中不存在此key）
        /// </summary>
        /// <param name="key">key</param>
        /// <param name="value">value</param>
        /// <returns>True if success</returns>
        public bool Add(string key, string value)
        {
            return client.Store(Enyim.Caching.Memcached.StoreMode.Add, key, value);
        }

        /// <summary>
        /// 增加一个缓存值（仅缓存中不存在此key）
        /// </summary>
        /// <param name="key">key</param>
        /// <param name="value">value</param>
        /// <param name="dt">过期时间</param>
        /// <returns>True if success</returns>
        public bool Add(string key, string value, DateTime dt)
        {
            return client.Store(Enyim.Caching.Memcached.StoreMode.Add, key, value, dt);
        }

        /// <summary>
        /// 增加一个缓存值（仅缓存中不存在此key）
        /// </summary>
        /// <typeparam name="T">T</typeparam>
        /// <param name="key">key</param>
        /// <param name="t">T</param>
        /// <returns>true if success</returns>
        public bool Add<T>(string key, T t)
        {
            return client.Store(Enyim.Caching.Memcached.StoreMode.Add, key, t);
        }

        /// <summary>
        /// 增加一个缓存值（仅缓存中不存在此key）
        /// </summary>
        /// <typeparam name="T">T</typeparam>
        /// <param name="key">key</param>
        /// <param name="t">T</param>
        /// <param name="dt">过期时间</param>
        /// <returns>true if success</returns>
        public bool Add<T>(string key, T t, DateTime dt)
        {
            return client.Store(Enyim.Caching.Memcached.StoreMode.Add, key, t, dt);
        }
        #endregion

        #region 替换缓存值
        /// <summary>
        /// 替换一个缓存值（仅缓存中已存在此key）
        /// </summary>
        /// <param name="key">key</param>
        /// <param name="value">value</param>
        /// <returns>true if success</returns>
        public bool Replace(string key, string value)
        {
            return client.Store(Enyim.Caching.Memcached.StoreMode.Replace, key, value);
        }

        /// <summary>
        /// 替换一个缓存值（仅缓存中已存在此key）
        /// </summary>
        /// <param name="key">key</param>
        /// <param name="value">value</param>
        /// <param name="dt">过期时间</param>
        /// <returns>true if success</returns>
        public bool Replace(string key, string value, DateTime dt)
        {
            return client.Store(Enyim.Caching.Memcached.StoreMode.Replace, key, value, dt);
        }

        /// <summary>
        /// 替换一个缓存值（仅缓存中已存在此key）
        /// </summary>
        /// <typeparam name="T">T</typeparam>
        /// <param name="key">key</param>
        /// <param name="t">T</param>
        /// <returns>true if success</returns>
        public bool Replace<T>(string key, T t)
        {
            return client.Store(Enyim.Caching.Memcached.StoreMode.Replace, key, t);
        }

        /// <summary>
        /// 替换一个缓存值（仅缓存中已存在此key）
        /// </summary>
        /// <typeparam name="T">T</typeparam>
        /// <param name="key">key</param>
        /// <param name="t">T</param>
        /// <param name="dt">过期时间</param>
        /// <returns>true if success</returns>
        public bool Replace<T>(string key, T t, DateTime dt)
        {
            return client.Store(Enyim.Caching.Memcached.StoreMode.Replace, key, t, dt);
        }
        #endregion

        #region 设置缓存值
        /// <summary>
        /// 设置缓存值，当该key存在时覆盖，不存在则新增
        /// </summary>
        /// <param name="key">key</param>
        /// <param name="value">value</param>
        /// <returns>true if success</returns>
        public bool Set(string key, string value)
        {
            return client.Store(Enyim.Caching.Memcached.StoreMode.Set, key, value);
        }

        /// <summary>
        /// 设置缓存值，当该key存在时覆盖，不存在则新增
        /// </summary>
        /// <param name="key">key</param>
        /// <param name="value">value</param>
        /// <param name="dt">过期时间</param>
        /// <returns>true if success</returns>
        public bool Set(string key, string value, DateTime dt)
        {
            return client.Store(Enyim.Caching.Memcached.StoreMode.Set, key, value, dt);
        }

        /// <summary>
        /// 设置缓存值，当该key存在时覆盖，不存在则新增
        /// </summary>
        /// <typeparam name="T">T</typeparam>
        /// <param name="key">key</param>
        /// <param name="t">T</param>
        /// <returns>true if success</returns>
        public bool Set<T>(string key, T t)
        {
            return client.Store(Enyim.Caching.Memcached.StoreMode.Set, key, t);
        }

        /// <summary>
        /// 设置缓存值，当该key存在时覆盖，不存在则新增
        /// </summary>
        /// <typeparam name="T">T</typeparam>
        /// <param name="key">key</param>
        /// <param name="t">T</param>
        /// <param name="dt">过期时间</param>
        /// <returns>true if success</returns>
        public bool Set<T>(string key, T t, DateTime dt)
        {
            return client.Store(Enyim.Caching.Memcached.StoreMode.Set, key, t, dt);
        }

        /// <summary>
        /// 带CAS设置缓存值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="t"></param>
        /// <param name="cas"></param>
        /// <returns>设置成功返回值和版本，失败则返回 NULL</returns>
        public MemcachedValue Set(string key, object value, ulong cas)
        {
            var result = client.ExecuteCas(Enyim.Caching.Memcached.StoreMode.Set, key, value, cas);
            if (result.Success)
            {
                return new MemcachedValue()
                {
                    Value = value,
                    Version = cas
                };
            }
            return null;
        }

        public MemcachedValue Set(string key, object value, DateTime dt, ulong cas)
        {
            var result = client.ExecuteCas(Enyim.Caching.Memcached.StoreMode.Set, key, value, dt, cas);
            if (result.Success)
            {
                return new MemcachedValue()
                {
                    Value = value,
                    Version = cas
                };
            }
            return null;
        }
        #endregion

        #region 移除一个缓存
        /// <summary>
        /// 移除一个缓存
        /// </summary>
        /// <param name="key">key</param>
        /// <returns>true if success</returns>
        public bool Delete(string key)
        {
            return client.Remove(key);
        }
        #endregion

        #endregion

        #region ICache实现
        /// <summary>
        /// 获取一个缓存值
        /// </summary>
        /// <param name="key">key</param>
        /// <returns>MemcachedValue</returns>
        public object Get(string key)
        {
            return GetWithCas(key);
        }

        /// <summary>
        /// 批量获取缓存值
        /// </summary>
        /// <param name="keys"></param>
        /// <returns> MemcachedValue词典 </returns>
        public IDictionary<string, object> Gets(IEnumerable<string> keys)
        {
            return (IDictionary<string, object>)GetMultiWithCas(keys);
        }

        /// <summary>
        /// 增加一个缓存
        /// </summary>
        /// <param name="key">key</param>
        /// <param name="value">MemcachedValue</param>
        /// <param name="timeout">过期时间(单位：毫秒)</param>
        public void Insert(string key, object value, int timeout)
        {
            MemcachedValue mv = value as MemcachedValue;
            if (mv == null)
            {
                throw new Exception("类型转换异常，请检查参数！");
            }
            //不带CAS的SET
            if (mv.Version == 0)
            {
                Set(key, mv.Value, DateTime.Now.AddMilliseconds(timeout));
            }
            else
            {
                Set(key, mv.Value, DateTime.Now.AddMilliseconds(timeout), mv.Version);
            }
        }

        /// <summary>
        /// 清除单个缓存
        /// </summary>
        /// <param name="key">key</param>
        /// <returns>被清除的缓存对象实例的缓存对象实例MemcachedValue，失败则返回NULL</returns>
        public object Remove(string key)
        {
            MemcachedValue mv = GetWithCas(key);
            if (Delete(key))
            {
                return mv;
            }
            return null;
        }

        /// <summary>
        /// 清除所有缓存（未实现）
        /// </summary>
        public void RemoveAll()
        {
            throw new NotImplementedException();
        }
        #endregion
    }
}
